
package com.yuanmei.datas;

import com.yuanmei.common.Utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.zip.InflaterInputStream;

import javolution.io.Struct;


@SuppressWarnings("deprecation")
public class PyTdxBase {
    private static final String TAG = PyTdxBase.class.getName();
    private final static boolean DEBUG = false;
    public static final String[] SERVERS = {
            "招商证券-深圳行情 % 119.147.212.81:7709",
            "华西证券-深证云重庆电信 % 222.180.170.195:7709",
            "华西证券-深证云重庆联通 % 113.207.108.73:7709",
            "WP_CHOOSE % 115.238.56.198:7709",
            "WP_CHOOSE % 115.238.90.165:7709",
            "WP_CHOOSE % 180.153.18.170:7709",
            "WP_CHOOSE % 218.75.126.9:7709",
            "WP_CHOOSE % 60.12.136.250:7709",
            "WP_CHOOSE % 60.191.117.167:7709",
            "WP_CHOOSE % jstdx.gtjas.com:7709",
            "WP_CHOOSE % shtdx.gtjas.com:7709",
            "WP_CHOOSE % sztdx.gtjas.com:7709",
    };

    private static String hq_server_host = "119.147.212.81"; // default
    private static int hq_server_port = 7709;

    public static void setServer(String serverInfo) {
        String server = serverInfo.split("%")[1].trim();
        String host = server.split(":")[0];
        int port = Integer.parseInt(server.split(":")[1]);
        hq_server_host = host;
        hq_server_port = port;
    }

    private static boolean checkServer(String host, int port) {
        try {
            SocketAddress remoteAddress = new InetSocketAddress(host, port);
            Socket client = new Socket();
            client.connect(remoteAddress, 5000);
            client.close();
            return true;
        } catch (NullPointerException e) {
            System.out.println("PyTDX Base connect " + host + " meet NullPointerException=" + e);
        } catch (IOException e) {
            System.out.println("PyTDX Base connect " + host + " meet IOException=" + e);
        }
        return false;
    }

    private static boolean autoSelectServer() {
        try {
            for (String serverInfo : SERVERS) {
                String server = serverInfo.split("%")[1].trim();
                String host = server.split(":")[0];
                int port = Integer.parseInt(server.split(":")[1]);
                if (checkServer(host, port)) {
                    hq_server_host = host;
                    hq_server_port = port;
                    System.out.println("PyTDX auto select " + hq_server_host + ":" + hq_server_port);
                    return true;
                }
            }
        } catch (NullPointerException e) {
            System.out.println("PyTDX Base auto select fail for NullPointerException=" + e);
        }
        return false;
    }

    static String getServerHost() {
        return hq_server_host;
    }

    static int getServerPort() {
        return hq_server_port;
    }


    public static class TdxResponseHeader extends Struct {
        private final Unsigned32 pad0 = new Unsigned32();
        private final Unsigned32 pad1 = new Unsigned32();
        private final Unsigned32 pad2 = new Unsigned32();
        private final Unsigned16 zipsize = new Unsigned16();
        private final Unsigned16 unzipsize = new Unsigned16();

        @Override
        public boolean isPacked() {
            return true; // 一定要加上这个，不然会出现对齐的问题
        }

        @Override
        public ByteOrder byteOrder() {
            return ByteOrder.LITTLE_ENDIAN; // 设置为小端数据
        }
    }

    static byte[] getResponse(InputStream in) throws IOException {
        TdxResponseHeader header = new TdxResponseHeader();
        header.read(in);
        int zipsize = header.zipsize.get();
        int unzipsize = header.unzipsize.get();
        if (DEBUG) {
            byte[] headArray = new byte[header.size()];
            header.getByteBuffer().flip();
            header.getByteBuffer().get(headArray);
            System.out.println("Get response header:" + Utils.byteArrayToHexString(headArray));
        }
        System.out.println("Response: zipsize=" + zipsize + ", unzipsize=" + unzipsize);
        if (zipsize == 0) {
            throw new IOException("Receive response header's zipsize is zero");
        }

        byte[] buffer = new byte[1024];
        int len;
        ByteArrayOutputStream zipByteArrayStream = new ByteArrayOutputStream();
        int recv_len = 0;
        while ((len = in.read(buffer)) > 0) {
            zipByteArrayStream.write(buffer, 0, len);
            recv_len += len;
            if (recv_len >= zipsize) {
                if (DEBUG) {
                    System.out.println("receive full zip body recv_len=" + recv_len);
                }
                break;
            }
        }
        byte[] zipArray = zipByteArrayStream.toByteArray();
        if (recv_len != zipsize) {
            throw new IOException("Receive zip buffer len:" + recv_len + " != zipsize:" + zipsize);
        }
        if (zipsize == unzipsize) {
            if (DEBUG) {
                System.out.println("receive body no need unzip");
            }
            return zipArray;
        }

        ByteArrayOutputStream unzipStream = new ByteArrayOutputStream();
        InflaterInputStream zipInputStream = new InflaterInputStream(new ByteArrayInputStream(zipArray));
        while ((len = zipInputStream.read(buffer)) > 0) {
            unzipStream.write(buffer, 0, len);
        }
        zipInputStream.close();
        byte[] unzipArray = unzipStream.toByteArray();
        if (unzipsize != unzipArray.length) {
            throw new IOException("Unzip byteArray length:" + unzipArray.length + " != unzipsize:" + unzipsize);
        }
        if (DEBUG) {
            System.out.println("unzipArray length=" + unzipArray.length);
        }
        return unzipArray;
    }

    private static void setup_cmd(Socket client, String hex_cmd) throws IOException {
        OutputStream out = client.getOutputStream();
        InputStream in = client.getInputStream();
        out.write(Utils.hexStringToByteArray(hex_cmd));
        out.flush();
        getResponse(in);
    }

    static void run_setup(Socket client) throws IOException {
        // setup cmd1
        setup_cmd(client, "0c 02 18 93 00 01 03 00 03 00 0d 00 01");
        // setup cmd2
        setup_cmd(client, "0c 02 18 94 00 01 03 00 03 00 0d 00 02");
        // setup cmd3
        setup_cmd(client, "0c 03 18 99 00 01 20 00 20 00 db 0f d5" +
                "d0 c9 cc d6 a4 a8 af 00 00 00 8f c2 25" +
                "40 13 00 00 d5 00 c9 cc bd f0 d7 ea 00" +
                "00 00 02");
    }

    static int[] get_price(ByteBuffer data, int pos) {
        int[] results = new int[2];
        int pos_byte = 6;
        int bdata = data.get(pos);
        int intdata = bdata & 0x3f;
        boolean sign = false;
        if (0 != (bdata & 0x40)) {
            sign = true;
        }

        while (0 != (bdata & 0x80)) {
            pos += 1;
            bdata = data.get(pos);
            intdata += (bdata & 0x7f) << pos_byte;
            pos_byte += 7;
        }

        pos += 1;
        if (sign) {
            intdata = -intdata;
        }

        results[0] = intdata;
        results[1] = pos;

        return results;
    }


}
